package kr.zetaomicron.ultrasolitaire;

import javax.microedition.khronos.opengles.GL10;

import android.util.Log;

import kr.zetaomicron.framework.gl.Animation;
import kr.zetaomicron.framework.gl.Camera2D;
import kr.zetaomicron.framework.gl.SpriteBatcher;
import kr.zetaomicron.framework.gl.Texture;
import kr.zetaomicron.framework.gl.TextureRegion;
import kr.zetaomicron.framework.impl.GLGraphics;

public class WorldRenderer {
    static final float FRUSTUM_WIDTH = Settings.WORLD_WIDTH;
    static final float FRUSTUM_HEIGHT = Settings.WORLD_HEIGHT;    
    GLGraphics glGraphics;
    World world;
    Camera2D cam;
    SpriteBatcher batcher;
    
    public WorldRenderer(GLGraphics glGraphics, SpriteBatcher batcher, World world) {
        this.glGraphics = glGraphics;
        this.world = world;
        this.cam = new Camera2D(glGraphics, FRUSTUM_WIDTH, FRUSTUM_HEIGHT);
        this.batcher = batcher;
    }
    
    public void render(float deltaTime) {
//    	if (world.bob.position.x < Settings.WORLD_HEIGHT / 2)	cam.position.x = Settings.WORLD_HEIGHT / 2;
//	    else if (world.bob.position.x > Settings.nLevelCols * Settings.LVL_TILE_SIZE - Settings.WORLD_HEIGHT / 2)
//	    	cam.position.x = Settings.nLevelCols * Settings.LVL_TILE_SIZE - Settings.WORLD_HEIGHT / 2;
//	    else	cam.position.x = world.bob.position.x;
//	    if (world.bob.position.y < Settings.WORLD_WIDTH / 2)	cam.position.y = Settings.WORLD_WIDTH / 2;
//	    else if (world.bob.position.y > Settings.nLevelRows * Settings.LVL_TILE_SIZE - Settings.WORLD_WIDTH / 2)
//	    	cam.position.y = Settings.nLevelRows * Settings.LVL_TILE_SIZE - Settings.WORLD_WIDTH / 2;
//	    else	cam.position.y = world.bob.position.y;
    	cam.position.x = Settings.WORLD_WIDTH / 2;
    	cam.position.y = Settings.WORLD_HEIGHT / 2;

        cam.setViewportAndMatrices();
        renderBackground();
        renderObjects(deltaTime);        
    }

    public void renderBackground() {
    	GL10 gl = glGraphics.getGL();

        gl.glEnable(GL10.GL_BLEND);
        batcher.beginBatch(Assets.tex_bg);
        batcher.drawSprite(Settings.WORLD_WIDTH / 2, Settings.WORLD_HEIGHT / 2,
        		Settings.WORLD_HEIGHT, Settings.WORLD_WIDTH, -90, Assets.bg_bg);
        batcher.endBatch();

        gl.glDisable(GL10.GL_BLEND);
    }

    public void renderObjects(float deltaTime) {
//        GL10 gl = glGraphics.getGL();
//        gl.glEnable(GL10.GL_BLEND);
//        gl.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA);
//       	gl.glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
//        
//        batcher.beginBatch(Assets.items);
//        renderPlayer();
//        renderSquirrels();
//        renderCastle();
//        //renderPlatforms();
//        batcher.endBatch();
//        batcher.beginBatch(Assets.platformTexture);
		if (World.MODE_NONE != world.mViewMode) {
			renderCards(deltaTime);	renderNums();
		}
//        batcher.endBatch();
//        //renderDebug();
//        gl.glDisable(GL10.GL_BLEND);
    }

	private void renderCards(float deltaTime) {
		//CLUBS = 0, DIAS = 1, SPADES = 2, HEARTS = 3;
		//FLAMES = 4, SPROUTS = 5, BUBBLES = 6, WATERDROPS = 7;
		Texture tex[] = new Texture[8];
		tex[0] = Assets.tex_cards_clubs;	tex[1] = Assets.tex_cards_dias;
		tex[2] = Assets.tex_cards_spades;	tex[3] = Assets.tex_cards_hearts;
		tex[4] = Assets.tex_cards_waterdrops;	tex[5] = Assets.tex_cards_flames;
		tex[6] = Assets.tex_cards_bubbles;	tex[7] = Assets.tex_cards_sprouts;
		GL10 gl = glGraphics.getGL();
		int RANKS = 13 + 5 * Settings.gameSettings[2];

        gl.glEnable(GL10.GL_BLEND);
        for (int i = 0; i < world.GetCardAnchors().length; i++) {
        	// Skips this anchor for later
        	if (i == Settings.anchor2anchor[1])	continue;
        	renderCardAnchors(i, tex);
		}
        // Now renders the skipped anchor
        renderCardAnchors((int)Settings.anchor2anchor[1], tex);
        
        // Displays moving cards
        if (World.MODE_MOVE_CARD == world.mViewMode) {
	        MoveCard moveCard = world.GetMoveCards();
	        for (int i = 0; i < moveCard.GetCount(); ++i) {
	        	Card card = moveCard.GetCards()[i];
	        	int tmpValue = card.GetValue();
	        	if (tmpValue > RANKS - 3 && RANKS < 23) {	tmpValue += 23 - RANKS;	}
	        	batcher.beginBatch(tex[card.GetSuit()]);
				batcher.drawSprite(card.GetX(), card.GetY(), Card.HEIGHT, Card.WIDTH, -90, Assets.list_backs.get(tmpValue - 1));
				//Log.i("[WorldRenderer]", "[renderCards] card " + String.valueOf(i) + " == {" + String.valueOf(card.GetX()) + ", " + String.valueOf(card.GetY()));
				batcher.endBatch();
	        }
        } else if (World.MODE_CARD_SELECT == world.mViewMode) {
        	batcher.beginBatch(Assets.tex_bg);
        	batcher.drawSprite(Settings.WORLD_WIDTH / 2, Settings.WORLD_HEIGHT / 2, Settings.WORLD_WIDTH, Settings.WORLD_HEIGHT, Assets.bg_cardselblk);
        	batcher.endBatch();
        	SelectCard selectCard = world.GetSelectCards();
	        for (int i = 0; i < selectCard.GetFullCount(); ++i) {
	        	Card card = selectCard.GetCards()[i];
	        	int tmpValue = card.GetValue();
	        	if (tmpValue > RANKS - 3 && RANKS < 23) {	tmpValue += 23 - RANKS;	}
	        	batcher.beginBatch(tex[card.GetSuit()]);
				batcher.drawSprite(card.GetX(), card.GetY(), Card.HEIGHT, Card.WIDTH, -90, Assets.list_backs.get(tmpValue - 1));
				//Log.i("[WorldRenderer]", "[renderCards] card " + String.valueOf(i) + " == {" + String.valueOf(card.GetX()) + ", " + String.valueOf(card.GetY()));
				batcher.endBatch();
	        }
        }

        gl.glDisable(GL10.GL_BLEND);
	}
	
	private void renderNums() {
		GL10 gl = glGraphics.getGL();

		CardAnchor cardAnchor = world.GetCardAnchors()[0];	// DEAL_FROM
		float x = cardAnchor.mX, y = cardAnchor.mY;
		int cardCount = cardAnchor.GetCount(), hiddenCount = cardAnchor.GetHiddenCount();

        gl.glEnable(GL10.GL_BLEND);
        batcher.beginBatch(Assets.tex_bg);
        if (cardCount > 0) {
        	if (cardCount >= 100) {
        		batcher.drawSprite(x, y + Card.HEIGHT / 3, Card.HEIGHT / 3, Card.WIDTH / 3, -90, Assets.bg_list_numbers.get(cardCount / 100));
        		batcher.drawSprite(x, y, Card.HEIGHT / 3, Card.WIDTH / 3, -90, Assets.bg_list_numbers.get((cardCount % 100) / 10));
            	batcher.drawSprite(x, y - Card.HEIGHT / 3, Card.HEIGHT / 3, Card.WIDTH / 3, -90, Assets.bg_list_numbers.get(cardCount % 10));
        	} else if (cardCount >= 10) {
        		batcher.drawSprite(x, y + Card.HEIGHT / 6, Card.HEIGHT / 3, Card.WIDTH / 3, -90, Assets.bg_list_numbers.get(cardCount / 10));
            	batcher.drawSprite(x, y - Card.HEIGHT / 6, Card.HEIGHT / 3, Card.WIDTH / 3, -90, Assets.bg_list_numbers.get(cardCount % 10));
        	} else {	// cardCount 1 ~ 9
        		batcher.drawSprite(x, y, Card.HEIGHT / 3, Card.WIDTH / 3, -90, Assets.bg_list_numbers.get(cardCount));
        	}
        } else {
        	batcher.drawSprite(x, y, Card.WIDTH / 3, Card.WIDTH / 3, -90, Assets.bg_list_numbers.get(10));	// O mark
        }
        batcher.endBatch();

        gl.glDisable(GL10.GL_BLEND);
	}
	
	private void renderCardAnchors(int cardAnchorIdx, Texture tex[]) {
		int RANKS = 13 + 5 * Settings.gameSettings[2];
		CardAnchor cardAnchor = world.GetCardAnchors()[cardAnchorIdx];
		float newX = cardAnchor.GetCount() == 0 ? cardAnchor.mX : cardAnchor.GetCards()[cardAnchor.GetCount() - 1].GetX();
		float newXforGA = cardAnchor.mX;	// for Generic Anchors
		float newY = cardAnchor.mY;
		float oldX, oldY, oldX1 = 0;
		if (Settings.anchor2anchor[0] < 0) {	// moved from moveCard anchor
			oldX = world.GetMoveCards().GetCurrentPoint().x;
			oldY = world.GetMoveCards().GetCurrentPoint().y;
		} else {
			CardAnchor oldCardAnchor = world.GetCardAnchors()[(int)Settings.anchor2anchor[0]];
			oldX = oldCardAnchor.GetCount() == 0 ? oldCardAnchor.mX : oldCardAnchor.GetCards()[oldCardAnchor.GetCount() - 1].GetX();
			if (oldCardAnchor.GetType() == CardAnchor.GENERIC_ANCHOR)	oldX -= Settings.anchor2anchor[2] * Card.WIDTH / 4;
			//oldX = oldCardAnchor.GetCount() == 0 ? oldCardAnchor.mX : oldCardAnchor.GetOldX();
			oldY = oldCardAnchor.mY;
			//Log.i("[WorldRenderer]", "[renderCardAnchors] GetCards()... == " + oldX1 + ", GetOldX() == " + oldX);
		}
		float x = newX, y = newY, x1 = 0;
		if (cardAnchorIdx == Settings.anchor2anchor[1]) {
			x = (1 - Settings.anchor2anchor[3] * 5) * oldX + Settings.anchor2anchor[3] * 5 * newX;
			y = (1 - Settings.anchor2anchor[3] * 5) * oldY + Settings.anchor2anchor[3] * 5 * newY;
			x1 = (1 - Settings.anchor2anchor[3] * 5) * oldX1 + Settings.anchor2anchor[3] * 5 * newX;
//			if (Settings.anchor2anchor[3] < 0.2f) {
//				Log.i("[WorldRenderer]", "[renderCardAnchors] x == " + String.valueOf(x) + ", " + String.valueOf(x1));
//			}
		}
		
		Card[] cards = cardAnchor.GetCards();
		int cardCount = cardAnchor.GetCount(), hiddenCount = cardAnchor.GetHiddenCount();
		
		switch (cardAnchor.GetType()) {
		case CardAnchor.DEAL_FROM:
			batcher.beginBatch(Assets.tex_bg);
			batcher.drawSprite(newX, newY, Card.HEIGHT, Card.WIDTH, -90, Assets.bg_space_waste);
			batcher.endBatch();
			if (0 < cardCount) {
				if (2 <= cardCount) {	// displays the next card
					batcher.beginBatch(Assets.tex_cards_backs);
					batcher.drawSprite(newX, newY, Card.HEIGHT, Card.WIDTH, -90, Assets.list_backs.get(0));
					batcher.endBatch();
				}
				batcher.beginBatch(Assets.tex_cards_backs);
				batcher.drawSprite(x, y, Card.HEIGHT, Card.WIDTH, -90, Assets.list_backs.get(0));
				batcher.endBatch();
			}
			break;
		case CardAnchor.DEAL_TO:
			batcher.beginBatch(Assets.tex_bg);
			batcher.drawSprite(newX, newY, Card.HEIGHT, Card.WIDTH, -90, Assets.bg_space_waste);
			batcher.endBatch();
			if (0 < cardCount) {
				if (2 <= cardCount) {	// displays the next card
					int tmpValue_DEAL_TO1 = cards[cardCount - 2].GetValue();
					if (tmpValue_DEAL_TO1 > RANKS - 3 && RANKS < 23) {	tmpValue_DEAL_TO1 += 23 - RANKS;	}
					batcher.beginBatch(tex[cards[cardCount - 2].GetSuit()]);
					batcher.drawSprite(newX, newY, Card.HEIGHT, Card.WIDTH, -90, Assets.list_backs.get(tmpValue_DEAL_TO1 - 1));
					batcher.endBatch();
				}
				int tmpValue_DEAL_TO = cards[cardCount - 1].GetValue();
				if (tmpValue_DEAL_TO > RANKS - 3 && RANKS < 23) {	tmpValue_DEAL_TO += 23 - RANKS;	}
				batcher.beginBatch(tex[cards[cardCount - 1].GetSuit()]);
				batcher.drawSprite(x, y, Card.HEIGHT, Card.WIDTH, -90, Assets.list_backs.get(tmpValue_DEAL_TO - 1));
				batcher.endBatch();
			}
			break;
		case CardAnchor.SEQ_SINK:
			batcher.beginBatch(Assets.tex_bg);
			batcher.drawSprite(newX, newY, Card.HEIGHT, Card.WIDTH, -90, Assets.bg_space_waste);
			batcher.endBatch();
			if (0 < cardCount) {
				if (2 <= cardCount) {	// displays the next card
					int tmpValue_DEAL_TO1 = cards[cardCount - 2].GetValue();
					if (tmpValue_DEAL_TO1 > RANKS - 3 && RANKS < 23) {	tmpValue_DEAL_TO1 += 23 - RANKS;	}
					batcher.beginBatch(tex[cards[cardCount - 2].GetSuit()]);
					batcher.drawSprite(newX, newY, Card.HEIGHT, Card.WIDTH, -90, Assets.list_backs.get(tmpValue_DEAL_TO1 - 1));
					batcher.endBatch();
				}
				int tmpValue_DEAL_TO = cards[cardCount - 1].GetValue();
				if (tmpValue_DEAL_TO > RANKS - 3 && RANKS < 23) {	tmpValue_DEAL_TO += 23 - RANKS;	}
				batcher.beginBatch(tex[cards[cardCount - 1].GetSuit()]);
				batcher.drawSprite(x, y, Card.HEIGHT, Card.WIDTH, -90, Assets.list_backs.get(tmpValue_DEAL_TO - 1));
				batcher.endBatch();
			}
			break;
		case CardAnchor.GENERIC_ANCHOR:
			batcher.beginBatch(Assets.tex_bg);
			batcher.drawSprite(newXforGA, newY, Card.HEIGHT, Card.WIDTH, -90, Assets.bg_space_waste);
			batcher.endBatch();
			if (0 < cardCount) {
				int tmpValue;
				switch (cardAnchor.GetDisplay()) {
			    case GenericAnchor.DISPLAY_ALL:
			    	for (int j = 0; j < cardCount; j++) {
			    		tmpValue = cards[j].GetValue();
			    		if (tmpValue > RANKS - 3 && RANKS < 23) {	tmpValue += 23 - RANKS;	} 
			    		batcher.beginBatch(tex[cards[j].GetSuit()]);
						batcher.drawSprite(cards[j].GetX(), cards[j].GetY(), Card.HEIGHT, Card.WIDTH, -90, Assets.list_backs.get(tmpValue - 1));
						batcher.endBatch();
			    	}
			    	break;
			    case GenericAnchor.DISPLAY_HIDE:
			    	for (int j = 0; j < cardCount; j++) {
			    		tmpValue = cards[j].GetValue();
			    		if (tmpValue > RANKS - 3 && RANKS < 23) {	tmpValue += 23 - RANKS;	}
			    		batcher.beginBatch(Assets.tex_cards_backs);
						batcher.drawSprite(cards[j].GetX(), cards[j].GetY(), Card.HEIGHT, Card.WIDTH, -90, Assets.list_backs.get(0));
						batcher.endBatch();
			    	}
			    	break;
			    case GenericAnchor.DISPLAY_MIX:
			    	for (int j = 0; j < cardCount; j++) {
			    		tmpValue = cards[j].GetValue();
			    		if (tmpValue > RANKS - 3 && RANKS < 23) {	tmpValue += 23 - RANKS;	}
			    		if (j < hiddenCount) {
			    			batcher.beginBatch(Assets.tex_cards_backs);
							batcher.drawSprite(cards[j].GetX(), cards[j].GetY(), Card.HEIGHT, Card.WIDTH, -90, Assets.list_backs.get(0));
							batcher.endBatch();
			    		} else if (cardCount - j <= Settings.anchor2anchor[2] && cardAnchorIdx == Settings.anchor2anchor[1]) {
			    			//Log.i("[WorldRenderer]", "[renderCardAnchors] generic anchor display mix");
			    			batcher.beginBatch(tex[cards[j].GetSuit()]);
							batcher.drawSprite(x - cardAnchor.GetCurSpacing() * (j - cardCount + 1), y, Card.HEIGHT, Card.WIDTH, -90, Assets.list_backs.get(tmpValue - 1));
							batcher.endBatch();
//							if (Settings.anchor2anchor[3] < 0.2f && j == cardCount - 1) {
//								Log.i("[WorldRenderer]", "[renderCardAnchors] display mix x == " + String.valueOf(x) + ", " + String.valueOf(x1));
//							}
			    		} else {
			    			batcher.beginBatch(tex[cards[j].GetSuit()]);
							batcher.drawSprite(cards[j].GetX(), cards[j].GetY(), Card.HEIGHT, Card.WIDTH, -90, Assets.list_backs.get(tmpValue - 1));
							batcher.endBatch();
			    		}
			    	}
			    	break;
			    case GenericAnchor.DISPLAY_ONE:
			    	for (int j = 0; j < cardCount; j++) {
			    		tmpValue = cards[j].GetValue();
			    		if (tmpValue > RANKS - 3 && RANKS < 23) {	tmpValue += 23 - RANKS;	}
			    		if (cardAnchorIdx < cardCount - 1) {
			    			batcher.beginBatch(Assets.tex_cards_backs);
							batcher.drawSprite(cards[j].GetX(), cards[j].GetY(), Card.HEIGHT, Card.WIDTH, -90, Assets.list_backs.get(0));
							batcher.endBatch();
			    		} else {
			    			batcher.beginBatch(tex[cards[j].GetSuit()]);
							batcher.drawSprite(cards[j].GetX(), cards[j].GetY(), Card.HEIGHT, Card.WIDTH, -90, Assets.list_backs.get(tmpValue - 1));
							batcher.endBatch();
			    		}
			    	}
			    	break;
				}
			}
			break;
		default:
			batcher.beginBatch(Assets.tex_bg);
			batcher.drawSprite(x, y, Card.HEIGHT, Card.WIDTH, -90, Assets.bg_space_waste);
			batcher.endBatch();
			break;
		}
	}
}